import '../assets/js/jtopo-min.js'

//树节点
class treeNode {
    /*
    param: caseId:当前节点的Id
    param: level:当前节点的层次
    param: sortIndex:同一层次的排序索引
    param: flag:是类别还是指标 类别:0;指标:1
     */
    constructor(caseId, flag = 0, isRoot = false) {
        this.caseId = caseId

        this.level = 0
        this.parentId = 0
        this.sortIndex = 0

        this.flag = flag
        this.name = null
        this.jnode = null

        this.code = null
        this.unit = null
        this.tableName = null
        this.colNames = []
        this.modelCode = null
        this.isRoot = isRoot
    }


    add(scene, text, x, y) {
        let node = new window.JTopo.Node()
        node.font = "12px 黑体"
        node.fontColor = this.flag == 0 ? '255,255,255' : '0,0,0';
        node.textPosition = "Middle_Center"
        node.setSize(100, 60)  // 尺寸
        node.borderRadius = 5 // 圆角
        node.borderWidth = 2 // 边框的宽度
        node.borderColor = '255,255,255' //边框颜色
        // node.alpha = 0.7 //透明度
        node.fillColor = this.flag == 0 ? '64,158,255' : '115,255,223'
        node.text = text || (this.flag == 0 ? "请输入类别名称" : "请输入指标名称")
        // node.textOffsetX = -30;
        // 向下偏移 25像素
        node.textOffsetY = -8
        node.selected = true   //选中
        node.setLocation(x, y)
        node.caseId = this.caseId //增加一个唯一的Id，便于查找
        scene.add(node)  // 放入到场景中
        this.jnode = node
        this.name = text || (this.flag == 0 ? "请输入类别名称" : "请输入指标名称")
    }

    //更新参数设置信息
    update1(name, code, unit, tableName, colNames, modelCode) {
        this.name = name
        this.code = code
        this.unit = unit
        this.tableName = tableName
        this.colNames = colNames
        this.modelCode = modelCode
        //同时更新jNode的Text
        this.jnode.text = name || (this.flag == 0 ? "请输入类别名称" : "请输入指标名称")
    }

    //更新level、parentId、sortIndex信息
    update2(level, parentId, sortIndex) {
        this.level = level
        this.parentId = parentId
        this.sortIndex = sortIndex
    }

}

//指标树
class indexTree {
    /*
        param: projectId:当前配置的Id
        param: headTitle:当前配置的title
     */

    constructor(canvasEleId, dragCallback) {
        this.projectId = null
        this.headTitle = null
        this.canvas = document.getElementById(canvasEleId)
        this.stage = new window.JTopo.Stage(this.canvas)
        this.scene = new window.JTopo.Scene(this.stage)
        this.scene.alpha = 1
        this.treeNodes = []
        this.originX = 300
        this.originY = 250
        this.curSelectedNode = null
        this.isDraging = false
        this.rootNode = null
        this.dragCallback = dragCallback  //拖动节点回调函数
        this.dragTargetJNode = null   //拖动时叠置到的节点

        let that = this
        this.scene.click(function (event) {
            console.log('e')
            // if (event.target == null) return;
            // let e = event.target;
            // if (e.elementType == 'node') {
            //     that.selectTreeNode(e)
            //     that.flashNode(e, 5)
            // }
            if(event.target == null) {
                if (that.curSelectedNode) {
                    that.curSelectedNode.jnode.selected = true
                }
                return
            }
        })

        this.scene.addEventListener("mousedrag", function (event) {
            if (event.target == null) return
            let e = event.target
            if (event.button == 0) {
                if (e.elementType == 'node') {
                    that.isDraging = true
                    console.log("开始拖拽...")
                    if (that.dragTargetJNode) that.highlightJnode(that.dragTargetJNode, false)
                    that.dragTargetJNode = that.scene.getElementByXY(e.x, e.y)
                    if (that.dragTargetJNode) {
                        that.highlightJnode(that.dragTargetJNode, true)
                    }
                }
            } else {
                //点击右键和中键结束
                console.log("右键结束拖拽")
                that.highlightJnode(that.dragTargetJNode, false)
                that.isDraging = false
            }
        })

        this.scene.addEventListener("mouseup", function (event) {
            if (event.target == null) return
            let e = event.target
            if (event.button == 0 && e.elementType == 'node') {
                console.log('松开左键,拖拽结束')
                that.selectTreeNode(e)
                that.findElementsByEnv(e.x, e.y)
            }
        })

        this.scene.addEventListener("mousewheel", function (e) {
        //   if (e.ctrlKey == true) {
                if (e.wheelDelta) {  //判断浏览器IE，谷歌滑轮事件
                    if (e.wheelDelta > 0) { //当滑轮向上滚动时
                        that.jZoomIn()
                    }
                    if (e.wheelDelta < 0) { //当滑轮向下滚动时
                        that.jZoomOut()
                    }
                } else if (e.detail) {  //Firefox滑轮事件
                    if (e.detail > 0) { //当滑轮向下滚动时
                        that.jZoomOut()
                    }
                    if (e.detail < 0) { //当滑轮向上滚动时
                        that.jZoomIn()
                    }
                }
         //   }
        });
    }

    set selectedNode(value) {
        this.curSelectedNode = value
    }

    get selectedNode() {
        return this.curSelectedNode
    }

    //清除选中节点
    clearSelect() {
        for (let i = 0; i < this.treeNodes.length; i++) {
            let treeNode = this.treeNodes[i]
            treeNode.jnode.selected = false;
        }
    }

    //选择某一节点
    selectTreeNode(jNode) {
        for (let i = 0; i < this.treeNodes.length; i++) {
            let tNode = this.treeNodes[i]
            tNode.jnode.selected = false
            if (tNode.jnode == jNode) {
                this.curSelectedNode = tNode
                tNode.jnode.selected = true
            }
        }
    }

    flashNode(node, flashTimes) {
        if (flashTimes == 0) {
            node.selected = true
            return;
        }
        node.selected = !node.selected;
        let that = this
        setTimeout(function () {
            that.flashNode(node, flashTimes - 1);
        }, 300);
    }


    addTreeNode(caseId, text, flag = 0, isRoot = false) {
        this.clearSelect()
        let tnode = new treeNode(caseId, flag, isRoot)
        tnode.add(this.scene, text, this.originX, this.originY)
        this.treeNodes.push(tnode)
        this.curSelectedNode = tnode
        if (isRoot) {
            this.rootNode = tnode
        }
        return tnode
    }

    addLink(treeNode1, treeNode2) {
        //设置treeNode2的parentId
        treeNode2.level = treeNode1.level + 1
        treeNode2.parentId = treeNode1.caseId
        let link = new window.JTopo.Link(treeNode1.jnode, treeNode2.jnode)
        link.strokeColor = '204,204,204'
        link.lineWidth = 1
        link.fromTNode = treeNode1
        link.toTNode = treeNode2
        this.scene.add(link)
    }

    delSelect() {   //递归删除
        if (this.curSelectedNode) {
            //console.log('curSelectedNode:' + this.curSelectedNode.caseId + ';' + 'parentId:' + this.curSelectedNode.parentId)
            let delNodes = []
            for (let i = 0; i < this.treeNodes.length; i++) {
                let tNode = this.treeNodes[i]
                //console.log('treeNode:' + this.curSelectedNode.caseId + ';' + 'parentId:' + this.curSelectedNode.parentId)
                if (tNode.parentId == this.curSelectedNode.caseId) {
                    //找到子结点，也一并删除
                    delNodes.push(tNode)
                }
            }
            //删除子结点
            for (let j = 0; j < delNodes.length; j++) {
                let tNode = delNodes[j]
                this.scene.remove(tNode.jnode)
                this.treeNodes.splice(this.treeNodes.findIndex(item => item == tNode), 1)
            }
            //1 删除jNode
            this.scene.remove(this.curSelectedNode.jnode)
            //2 从list中移除
            this.treeNodes.splice(this.treeNodes.findIndex(item => item == this.curSelectedNode), 1)
            //3 再次选中一个节点
            if (this.treeNodes.length > 0) {
                let tNode=this.treeNodes[this.treeNodes.length-1]
                this.curSelectedNode = tNode
                tNode.jnode.selected = true
            }
        }
    }

    doLayout() {
        this.scene.doLayout(window.JTopo.layout.TreeLayout('right', 100, 200));
    }

    jCenter() {    //居中
        this.scene.centerAndZoom()
    }

    jZoomIn() {   //放大
        this.scene.zoomOut()
    }

    jZoomOut() {   //缩小
        this.scene.zoomIn()
    }

    jExport() {     //导出
        this.stage.saveImageInfo()
    }

    highlightJnode(jNode, isHighlight) {  //
        if (isHighlight) {
            jNode.borderWidth = 4 // 边框的宽度
            jNode.borderColor = '255,215,0' //边框颜色
        } else {
            jNode.borderWidth = 2 // 边框的宽度
            jNode.borderColor = '255,255,255' //边框颜色
        }
    }

    isSubNodeOfParent(selectedNode,targetNode){
        if(targetNode.parentId){
            if(selectedNode.caseId == targetNode.parentId){
                return true
            }else{
                let node = this.findTreeNodeById(targetNode.parentId)
                return this.isSubNodeOfParent(selectedNode,node)
            }
        }else{
            return false
        }
    }

    findElementsByEnv(x, y) {    //根据当前位置选择交叉的节点
        if (this.isDraging) {
            let targetJNode = this.scene.getElementByXY(x, y)
            if (targetJNode == null) {
                this.isDraging = false
                return
            }
            let targetTNode = this.findTreeNodeById(targetJNode.caseId)
            if (targetTNode == null) {
                this.isDraging = false
                if (this.dragTargetJNode) this.highlightJnode(this.dragTargetJNode, false)
                return
            }
            //判断当前节点是否允许移动，父节点不能放子节点后面
            let isSubNode = this.isSubNodeOfParent(this.curSelectedNode, targetTNode)
            if(isSubNode){
                this.isDraging = false
                this.dragCallback("父节点不能拖拽至其子节点后面!")
                this.doLayout()
                if (this.dragTargetJNode) this.highlightJnode(this.dragTargetJNode, false)
                return
            }
            //判断当前节点是否允许移动，必须值指标跟在类别后面
            if (targetTNode.flag == 1 && this.curSelectedNode.flag == 0) {
                this.isDraging = false
                this.dragCallback("类别不能拖拽至指标后面!")
                this.doLayout()
                if (this.dragTargetJNode) this.highlightJnode(this.dragTargetJNode, false)
                return
            }
            //移除之前的link
            let curParentTNode = this.findTreeNodeById(this.curSelectedNode.parentId)
            let link = this.findLinkByTNode(curParentTNode, this.curSelectedNode)
            this.scene.remove(link)
            //增加link
            this.addLink(targetTNode, this.curSelectedNode)
            this.doLayout()
            if (this.dragTargetJNode) this.highlightJnode(this.dragTargetJNode, false)
            //释放标识
            this.isDraging = false
        }
    }

    //查找link
    findLinkByTNode(treeNode1, treeNode2) {
        let links = this.scene.getElementsByClass(window.JTopo.Link)
        for (let i = 0; i < links.length; i++) {
            let link = links[i]
            if (link.fromTNode == treeNode1 && link.toTNode == treeNode2) {
                return link
            }
        }
        return null
    }

    findTreeNodeById(caseId) {
        for (let i = 0; i < this.treeNodes.length; i++) {
            let tNode = this.treeNodes[i]
            if (tNode.caseId == caseId) {
                return tNode
            }
        }
        return null
    }

    //重新梳理节点树，更新level/sortIndex
    reorderTreeNodes() {
        let levels = {}
        for (let i = 0; i < this.treeNodes.length; i++) {
            let tNode = this.treeNodes[i]  //第一个节点肯定是根结点
            //更新level
            let parentNode = this.findTreeNodeById(tNode.parentId)
            if (parentNode == null) continue
            tNode.level = parentNode.level + 1
            if (!levels.hasOwnProperty(tNode.level)) {
                levels[tNode.level] = []
            }
            levels[tNode.level].push(tNode)
        }
        //更新sortIndex
        for (let level in levels) {
            let nodes = levels[level]
            for (let j = 0; j < nodes.length; j++) {
                nodes[j].sortIndex = j
            }
        }
    }

    getPostParams() {
        let result = []
        for (let i = 0; i < this.treeNodes.length; i++) {
            let tNode = this.treeNodes[i]
            result.push({
                name: tNode.name,
                code: tNode.code,
                unit: tNode.unit,
                caseId: tNode.caseId,
                parentId: tNode.parentId,
                level: tNode.level,
                sortIndex: tNode.sortIndex,
                projectId: this.projectId,
                headTitle: this.headTitle,
                flag: tNode.flag,
                tableName: tNode.tableName,
                modelCode: tNode.modelCode,
                columnName: tNode.colNames.length > 0 ? tNode.colNames[0] : ''
            })
        }
        return result
    }

    //重置指标树
    resetIndexTree() {
        this.projectId = null
        this.headTitle = null
        this.treeNodes = []
        this.curSelectedNode = null
        this.isDraging = false
        this.rootNode = null
        this.scene.clear()
    }

}

// export default treeNode
export default indexTree